package com.summer.filesync.manager.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.model.manager.RecycleBinItem;
import com.summer.filesync.util.Logger;
import java.io.IOException;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** 文件回收站服务 提供安全的文件删除和恢复功能 */
public class FileRecycleBinService {
  private static final Logger logger = Logger.getLogger(FileRecycleBinService.class);

  private final FileMetadataDAO fileMetadataDAO;
  private final ExecutorService recycleBinExecutor;
  private final Map<String, RecycleBinItem> recycleBinItems;
  private final String recycleBinDirectory;

  public FileRecycleBinService(FileMetadataDAO fileMetadataDAO) {
    this.fileMetadataDAO = fileMetadataDAO;
    this.recycleBinExecutor = Executors.newFixedThreadPool(2);
    this.recycleBinItems = new ConcurrentHashMap<>();
    this.recycleBinDirectory = System.getProperty("user.home") + "/.filesync/recycle_bin";

    // 确保回收站目录存在
    try {
      Files.createDirectories(Paths.get(recycleBinDirectory));
      loadRecycleBinItems();
    } catch (IOException e) {
      logger.error("无法创建回收站目录: " + recycleBinDirectory, e);
    }
  }

  /** 将文件移到回收站 */
  public CompletableFuture<Boolean> moveToRecycleBin(String filePath) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("将文件移到回收站: " + filePath);

          try {
            Path sourceFile = Paths.get(filePath);
            if (!Files.exists(sourceFile)) {
              logger.warn("文件不存在: " + filePath);
              return false;
            }

            // 创建回收站项目
            RecycleBinItem item = new RecycleBinItem();
            item.setOriginalPath(filePath);
            item.setFileName(sourceFile.getFileName().toString());
            item.setFileSize(Files.size(sourceFile));
            item.setDirectory(Files.isDirectory(sourceFile));

            // 生成唯一的回收站文件名
            String recycleBinFileName = item.getId() + "_" + sourceFile.getFileName().toString();
            Path recycleBinFile = Paths.get(recycleBinDirectory, recycleBinFileName);

            // 移动文件到回收站
            Files.move(sourceFile, recycleBinFile, StandardCopyOption.REPLACE_EXISTING);
            item.setRecycleBinPath(recycleBinFile.toString());

            // 保存回收站项目
            recycleBinItems.put(item.getId(), item);
            saveRecycleBinItems();

            logger.info("文件已移到回收站: " + filePath + " -> " + recycleBinFile);
            return true;

          } catch (Exception e) {
            logger.error("移动文件到回收站失败: " + filePath, e);
            return false;
          }
        },
        recycleBinExecutor);
  }

  /** 从回收站恢复文件 */
  public CompletableFuture<Boolean> restoreFromRecycleBin(String itemId) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("从回收站恢复文件: " + itemId);

          try {
            RecycleBinItem item = recycleBinItems.get(itemId);
            if (item == null) {
              logger.warn("回收站项目不存在: " + itemId);
              return false;
            }

            Path recycleBinFile = Paths.get(item.getRecycleBinPath());
            Path originalFile = Paths.get(item.getOriginalPath());

            if (!Files.exists(recycleBinFile)) {
              logger.warn("回收站文件不存在: " + item.getRecycleBinPath());
              return false;
            }

            // 检查原始位置是否已存在文件
            if (Files.exists(originalFile)) {
              // 生成新的文件名
              String newFileName = generateUniqueFileName(originalFile);
              originalFile = originalFile.getParent().resolve(newFileName);
              logger.info("原始位置已存在文件，恢复到新位置: " + originalFile);
            }

            // 确保目标目录存在
            Files.createDirectories(originalFile.getParent());

            // 恢复文件
            Files.move(recycleBinFile, originalFile, StandardCopyOption.REPLACE_EXISTING);

            // 从回收站移除项目
            recycleBinItems.remove(itemId);
            saveRecycleBinItems();

            logger.info("文件已从回收站恢复: " + originalFile);
            return true;

          } catch (Exception e) {
            logger.error("从回收站恢复文件失败: " + itemId, e);
            return false;
          }
        },
        recycleBinExecutor);
  }

  /** 永久删除回收站项目 */
  public CompletableFuture<Boolean> permanentlyDelete(String itemId) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("永久删除回收站项目: " + itemId);

          try {
            RecycleBinItem item = recycleBinItems.get(itemId);
            if (item == null) {
              logger.warn("回收站项目不存在: " + itemId);
              return false;
            }

            Path recycleBinFile = Paths.get(item.getRecycleBinPath());

            // 删除文件
            if (Files.exists(recycleBinFile)) {
              Files.delete(recycleBinFile);
            }

            // 从回收站移除项目
            recycleBinItems.remove(itemId);
            saveRecycleBinItems();

            logger.info("文件已永久删除: " + item.getOriginalPath());
            return true;

          } catch (Exception e) {
            logger.error("永久删除文件失败: " + itemId, e);
            return false;
          }
        },
        recycleBinExecutor);
  }

  /** 获取回收站所有项目 */
  public List<RecycleBinItem> getRecycleBinItems() {
    return new ArrayList<>(recycleBinItems.values());
  }

  /** 清空回收站 */
  public CompletableFuture<Integer> emptyRecycleBin() {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("清空回收站");

          int deletedCount = 0;
          List<String> itemIds = new ArrayList<>(recycleBinItems.keySet());

          for (String itemId : itemIds) {
            try {
              if (permanentlyDelete(itemId).get()) {
                deletedCount++;
              }
            } catch (Exception e) {
              logger.error("删除回收站项目失败: " + itemId, e);
            }
          }

          logger.info("回收站已清空，删除了 " + deletedCount + " 个项目");
          return deletedCount;
        },
        recycleBinExecutor);
  }

  /** 清理过期的回收站项目 */
  public CompletableFuture<Integer> cleanupExpiredItems(int retentionDays) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("清理过期的回收站项目，保留期: " + retentionDays + " 天");

          LocalDateTime cutoffTime = LocalDateTime.now().minusDays(retentionDays);
          int deletedCount = 0;

          List<String> expiredItemIds = new ArrayList<>();
          for (RecycleBinItem item : recycleBinItems.values()) {
            if (item.getDeletedTime().isBefore(cutoffTime)) {
              expiredItemIds.add(item.getId());
            }
          }

          for (String itemId : expiredItemIds) {
            try {
              if (permanentlyDelete(itemId).get()) {
                deletedCount++;
              }
            } catch (Exception e) {
              logger.error("删除过期回收站项目失败: " + itemId, e);
            }
          }

          logger.info("清理完成，删除了 " + deletedCount + " 个过期项目");
          return deletedCount;
        },
        recycleBinExecutor);
  }

  /** 获取回收站使用的总空间 */
  public long getRecycleBinSize() {
    long totalSize = 0;

    for (RecycleBinItem item : recycleBinItems.values()) {
      try {
        Path recycleBinFile = Paths.get(item.getRecycleBinPath());
        if (Files.exists(recycleBinFile)) {
          totalSize += Files.size(recycleBinFile);
        }
      } catch (Exception e) {
        // 忽略单个文件错误
      }
    }

    return totalSize;
  }

  /** 关闭回收站服务 */
  public void shutdown() {
    logger.info("文件回收站服务正在关闭...");
    saveRecycleBinItems();
    recycleBinExecutor.shutdown();
  }

  /** 生成唯一文件名 */
  private String generateUniqueFileName(Path originalFile) {
    String fileName = originalFile.getFileName().toString();
    String baseName;
    String extension;

    int lastDot = fileName.lastIndexOf('.');
    if (lastDot > 0) {
      baseName = fileName.substring(0, lastDot);
      extension = fileName.substring(lastDot);
    } else {
      baseName = fileName;
      extension = "";
    }

    int counter = 1;
    while (Files.exists(originalFile.getParent().resolve(baseName + "_恢复" + counter + extension))) {
      counter++;
    }

    return baseName + "_恢复" + counter + extension;
  }

  /** 加载回收站项目 */
  private void loadRecycleBinItems() {
    // 简化实现，实际应从持久化存储加载
    logger.debug("加载回收站项目");
  }

  /** 保存回收站项目 */
  private void saveRecycleBinItems() {
    // 简化实现，实际应保存到持久化存储
    logger.debug("保存回收站项目，当前项目数: " + recycleBinItems.size());
  }
}
